#include "BluetoothSerial.h"

#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

BluetoothSerial SerialBT;
String data = "";
unsigned long last_time = 0;

int Red_Led = 17;
int Green_Led = 18;
int UV_Light = 19;
int Pump = 21;
int value = 0;

#define VREF 1
#define SCOUNT 30
#define TdsSensorPin 33

int analogBuffer[SCOUNT];
int analogBufferTemp[SCOUNT];
int analogBufferIndex = 0, copyIndex = 0;
float averageVoltage = 0, tdsValue = 0, temperature = 25;

const int potPin = 35;
float Value = 0;

int AOUT_PIN = 32;
int sensor1 = 22;
int sensor2 = 23;

int Moil = 0;
int val = 0;
int val1 = 0;
int val2 = 0;
int x = 0;

void setup() {
  Serial.begin(115200);
  SerialBT.begin("Hydroponic_Project");

  pinMode(potPin, INPUT);
  pinMode(sensor1, INPUT);
  pinMode(sensor2, INPUT);
  pinMode(TdsSensorPin, INPUT);
  pinMode(AOUT_PIN, INPUT);

  pinMode(UV_Light, OUTPUT);
  pinMode(Pump, OUTPUT);
  pinMode(Red_Led, OUTPUT);
  pinMode(Green_Led, OUTPUT);

  digitalWrite(Red_Led, LOW);
  digitalWrite(Green_Led, HIGH);
  digitalWrite(Pump, LOW);
  digitalWrite(UV_Light, HIGH);
}

void loop() {
  data="";
  Moil = analogRead(AOUT_PIN);
  Value = analogRead(potPin);
  int val = map(Moil, 0, 4095, 100, 0);
  int PH = map(Value, 0, 4095, 127, 0);
  int tds = map(tdsValue, 0, 500, 0, 100);
  SerialBT.print(String(val) + ";" + String(tds) + ";" + String(PH) + ";");
  int val1 = digitalRead(sensor1);
  int val2 = digitalRead(sensor2);
  if (val1 == 0 and val2 == 0 and x == 0) {
    digitalWrite(UV_Light, HIGH);
  } else if (val1 == 1 and val2 == 1 and x == 0) {
    digitalWrite(UV_Light, LOW);
  }
  if (millis() - last_time > 10000) {
    last_time = millis();
  }

  if (SerialBT.available()) {
    while (SerialBT.available()) {
      char incomingByte = SerialBT.read();
      data += incomingByte;
    }
    Serial.println("data = " + String(data));
    delay(20);
  }
  if (data == "BT_Conn") {
    digitalWrite(Green_Led, LOW);
    digitalWrite(Red_Led, HIGH);
    data = "";
    x = 1;
  } else if (data == "off_led" and x == 1) {
    digitalWrite(UV_Light, HIGH);
    data = "";
  } else if (data == "on_led" and x == 1) {
    digitalWrite(UV_Light, LOW);
    data = "";
  } else if (data == "pump_off" and x == 1) {
    digitalWrite(Pump, HIGH);
    data = "";
  } else if (data == "pump_on" and x == 1) {
    digitalWrite(Pump, LOW);
    data = "";
  }
  if (data == "BT_Disconn") {
    digitalWrite(Green_Led, HIGH);
    digitalWrite(Red_Led, LOW);
    x = 0;
    delay(3500);
    ESP.restart();
  }

  static unsigned long analogSampleTimepoint = millis();
  if (millis() - analogSampleTimepoint > 40U) {
    analogSampleTimepoint = millis();
    analogBuffer[analogBufferIndex] = analogRead(TdsSensorPin);
    analogBufferIndex++;
    if (analogBufferIndex == SCOUNT)
      analogBufferIndex = 0;
  }
  static unsigned long printTimepoint = millis();
  if (millis() - printTimepoint > 800U) {
    printTimepoint = millis();
    for (copyIndex = 0; copyIndex < SCOUNT; copyIndex++)
      analogBufferTemp[copyIndex] = analogBuffer[copyIndex];
    averageVoltage = getMedianNum(analogBufferTemp, SCOUNT) * (float)VREF / 1024.0;
    float compensationCoefficient = 1.0 + 0.02 * (temperature - 25.0);
    float compensationVolatge = averageVoltage / compensationCoefficient;
    tdsValue = (133.42 * compensationVolatge * compensationVolatge * compensationVolatge - 255.86 * compensationVolatge * compensationVolatge + 857.39 * compensationVolatge) * 0.5;
  }
}
int getMedianNum(int bArray[], int iFilterLen) {
  int bTab[iFilterLen];
  for (byte i = 0; i < iFilterLen; i++)
    bTab[i] = bArray[i];
  int i, j, bTemp;
  for (j = 0; j < iFilterLen - 1; j++) {
    for (i = 0; i < iFilterLen - j - 1; i++) {
      if (bTab[i] > bTab[i + 1]) {
        bTemp = bTab[i];
        bTab[i] = bTab[i + 1];
        bTab[i + 1] = bTemp;
      }
    }
  }
  if ((iFilterLen & 1) > 0)
    bTemp = bTab[(iFilterLen - 1) / 2];
  else
    bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
  return bTemp;
}